home *** CD-ROM | disk | FTP | other *** search
- /* build.c --- Build the data structure as presented from the dvi file by
- dviread. */
-
- #include "d2rd.h"
- #include "bbc.h"
- #include "font.h"
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include "kernel.h"
- #include "visdelay.h"
- #include "template.h"
- #include "colourtran.h"
- #include "res.h"
- #include "flex.h"
-
- /* The allocation units while reading a dvi file. Maybe these could just be
- very large numbers, since the appriopriate arrays are re-alloc'd to the
- right size afterwards anyway, or maybe not... */
-
- #define RULE_BLOCKSIZE 10
- #define TEXT_BLOCKSIZE 100
- #define CHAR_BLOCKSIZE 200
-
-
- /* Set this variable to 1 to be blown away by gunge while loading a dvi file. */
-
- extern int debug;
-
-
- /* CURRENT_DVI_FILE points to the struct dvi_file of the file currently being read. */
-
- struct dvi_file *current_dvi_file;
-
-
- /* CURRENT_PAGE idem dito of the current page. PAGE_PTR points to the
- pointer which should point to this page, which it indeed will as soon as
- this page is completely loaded. */
-
- static struct page **page_ptr, *current_page;
-
-
- /* Possible \magstep values (magstep0, magstephalf, magstep1, ..., magstep5)
- in the order of the magnification submenu. */
-
- double tex_magstep[] = {1.000, 1.095, 1.200, 1.440, 1.728, 2.074, 2.488};
-
-
- /* The fonthandle while reading the dvi file, as set by the last call to
- setfont. */
-
- int current_font_handle;
-
-
- static int current_page_number;
-
- int draw_page = 1;
-
- int page_area_size;
-
- int loading_a_file;
-
- int x_os_scale, y_os_scale;
-
- int rule_index, char_index, text_index;
-
- int max_rule_index, max_char_index, max_text_index;
-
-
-
- struct
- {
- char val[1024];
- _kernel_swi_regs r;
- } old_font;
-
-
- /* This sets the Font$Path to my own fonts. It saves the old Font$Prefix
- properly, which can't be done by getenv () and setenv () in case the
- variable is something like a macro. Hence this _kernel_swi () stuff. */
-
- void
- set_font_path (void)
- {
- char *new_font_path;
-
- old_font.r.r[0] = (int) "Font$Path";
- old_font.r.r[1] = (int) &old_font.val[0];
- old_font.r.r[2] = 1024;
- old_font.r.r[3] = old_font.r.r[4] = 0;
- _kernel_swi (0x23, &old_font.r, &old_font.r);
-
- new_font_path = getenv ("PreviewFonts$Path");
- if (new_font_path == NULL)
- tfatal ("PreviewFonts$Path is not defined!");
-
- _kernel_setenv ("Font$Path", new_font_path);
- }
-
-
- void
- reset_font_path (void)
- {
- old_font.r.r[3] = 0;
- _kernel_swi (0x24, &old_font.r, &old_font.r);
- }
-
-
- /* Set the default values of a window. */
-
- void
- default_display_values (struct display *w)
- {
- w->hor_size = (int)(A4_WIDTH * MILLIPOINTS);
- w->ver_size = (int)(A4_HEIGHT * MILLIPOINTS);
- w->hor_offset = 1 * MILLIPOINTS; /* one inch, in millipoints */
- w->ver_offset = 1 * MILLIPOINTS; /* one inch, in millipoints */
- w->magstep = 0; w->mag_tweak = 1.0;
- w->zoom = 0;
- }
-
-
- void
- factors (struct display *w, double *x, double *y)
- {
- *x = *y = tex_magstep[w->magstep] * w->mag_tweak;
- }
-
-
- void
- fill_sprite (struct display *w)
- {
- struct dvi_file *f = w->file;
- struct font_use *fu;
- struct page *p = w->page;
- struct text *t;
- struct rule *l;
- wimp_palettestr current_palette;
- wimp_paletteword pal;
- _kernel_swi_regs r;
- int h, i, k, x, y, dvi_to_handle[256];
- int things = 0, bpp = bbc_vduvar (bbc_Log2BPP);
- double xs, ys;
-
- visdelay_begin ();
- set_font_path ();
-
- for (i = 0; i < 256; i++)
- dvi_to_handle[i] = 0;
-
- wimp_readpalette (¤t_palette);
-
- r.r[0] = 60 + 256;
- r.r[1] = (int) w->area;
- r.r[2] = (int) w->sid.s.name;
- r.r[3] = 0;
-
- err = (os_error *) _kernel_swi (0x2e, &r, &r);
- if (err)
- tfatal ("Can't redirect output to sprite: %s\n", err->errmess);
-
- /* Output is now to the sprite. */
-
- wimp_setpalette (¤t_palette);
-
- pal.word = -1; pal.bytes.gcol = 0;
- colourtran_setGCOL (pal, 128, 0, &i);
- bbc_clg ();
-
- factors (w, &xs, &ys);
-
- pal.word = -1;
-
- for (t = p->texts, i = 0; i < p->text_max; t++, i++)
- {
- /* If the dvi to handle translation results in 0, the font has not been
- found yet. Thus, find it at the appropriate size. */
-
- if (t->font > 255)
- tfatal ("fontno = %d\n", t->font);
-
- if (dvi_to_handle[t->font] == 0)
- {
- fu = f->fonts[t->font];
- err = font_find (fu->name, (int) (fu->size * xs), (int) (fu->size * ys), 0, 0, &dvi_to_handle[t->font]);
- if (err)
- {
- dvi_to_handle[t->font] = 0;
- continue;
- }
- }
-
- font_setcolour (dvi_to_handle[t->font], 0, 1, bpp == 0 ? 0 : bpp == 1 ? 2 : bpp == 2 ? 6 : 14);
- font_paint (&p->chars[t->text], 0, (int)(t->x * xs),
- (int)((w->ver_size - w->ver_offset - t->y) * ys));
- visdelay_percent ((100 * things++) / p->things);
- }
-
- for (i = 0; i < 256; i++)
- if (dvi_to_handle[i])
- font_lose (dvi_to_handle[i]);
-
- pal.word = 0;
- colourtran_setGCOL (pal, 0, 0, &i);
-
- for (l = p->rules, i = 0; i < p->rule_max; l++, i++)
- {
- visdelay_percent ((100 * things++) / p->things);
- font_converttoos ((int)(l->x * xs),
- (int)((w->ver_size - w->ver_offset - l->y) * ys), &x, &y);
- font_converttoos ((int) (l->w * xs), (int) (l->h * ys), &k, &h);
- bbc_rectanglefill (x, y, k, h);
- }
-
- /* Re-redirect output to the screen again. */
-
- _kernel_swi (0x2e, &r, &r);
-
- reset_font_path ();
-
- visdelay_percent (-1);
- visdelay_end ();
- } /* fill_sprite */
-
-
-
- /********
- */
-
- int
- define_sprite (struct display *w)
- {
- char *sprite_name = xmalloc (12);
- double xfac, yfac;
- int xpix, ypix;
- int size;
-
- factors (w, &xfac, &yfac);
-
- font_converttoos( (int)((w->hor_size - w->hor_offset) * xfac),
- (int)((w->ver_size - w->ver_offset) * yfac),
- &xpix, &ypix);
-
- xpix /= x_os_scale; xpix = (xpix+31) & ~31;
- ypix /= y_os_scale;
-
- size = (int) (1024 +
- (xpix * ypix * (1 << bbc_vduvar (bbc_Log2BPP))) / 8.0);
-
- #ifdef USE_FLEX
- if (flex_alloc ((flex_ptr) &w->area, size) == 0)
- tfatal ("failed to allocate space for aprite area");
- #else
- w->area = xmalloc (size);
- #endif
-
- sprite_area_initialise (w->area, size);
-
- sprintf (sprite_name, "page");
- w->sid.tag =0;
- w->sid.s.name = sprite_name;
-
- err = sprite_create (w->area, sprite_name, TRUE,
- xpix, ypix, vdu_mode);
- if (err)
- tfatal ("Can't create sprite: %s\n", err->errmess);
-
- return (0);
- } /* define_sprite */
-
-
-
- void
- adjust_window_size (struct display *w)
- {
- wimp_redrawstr r;
- wimp_wstate s;
- double xfac, yfac;
-
- factors (w, &xfac, &yfac);
-
- r.w = w->w_handle;
- r.box.x0 = 0;
- r.box.y0 = 0;
- font_converttoos((int)(w->hor_size*xfac), (int)(w->ver_size*yfac), &r.box.x1, &r.box.y1);
- wimpt_noerr (wimp_set_extent (&r));
-
- r.w = w->w_handle;
- r.box.x0 = 0;
- r.box.y0 = 0;
- r.box.x1 = 1 << 30;
- r.box.y1 = 1 << 30;
- wimpt_noerr (wimp_force_redraw (&r));
-
- wimp_get_wind_state (w->w_handle, &s);
- wimp_open_wind (&s.o);
- } /* adjust_window_size */
-
-
-
- void
- set_window_title (struct display *w)
- {
- wimp_wstate ws;
-
- sprintf (w->w_title, "%s %d%s", w->file->f_name, w->page->dvi_page, w->file->complete ? "" : " *");
- wimpt_noerr (wimp_get_wind_state (w->w_handle, &ws));
- ws.o.box.x1 -= 4;
- wimpt_noerr (wimp_open_wind (&ws.o));
- ws.o.box.x1 += 4;
- wimpt_noerr (wimp_open_wind (&ws.o));
- }
-
-
-
- void
- build_a_window (struct dvi_file *df, struct page *p)
- {
- struct display *w;
- wimp_wind *wind;
- wimp_openstr wop;
- double xfac, yfac;
-
- w = xcalloc (1, sizeof (struct display));
- w->file = df;
- w->page = p;
-
- w->w_title = xmalloc (300);
- sprintf (w->w_title, "%s", df->f_name);
-
- default_display_values (w);
- define_sprite (w);
- fill_sprite (w);
-
- wind = template_syshandle ("yesyes");
- factors (w, &xfac, &yfac);
-
- wind->ex.x0 = 0;
- wind->ex.y0 = 0;
- font_converttoos((int)(w->hor_size*xfac), (int)(w->ver_size*yfac),
- &wind->ex.x1, &wind->ex.y1);
- wind->titleflags |= wimp_ITEXT | wimp_INDIRECT ;
- wind->titleflags &= ~(wimp_ISPRITE);
- wind->title.indirecttext.buffer = w->w_title;
- wind->title.indirecttext.validstring = NULL;
- wind->title.indirecttext.bufflen = 300;
-
- wimpt_noerr (wimp_create_wind (wind, &w->w_handle));
-
- /*
- ** Having created the window, we now open it.
- ** Initially, the part of the work area we want visible
- ** is the middle of the topmost part. We can skip part
- ** of the top margin, too, as it won't have anything in it.
- */
- wop.w = w->w_handle;
- wop.box = wind->box;
- font_converttoos( 0, (int)((w->ver_size-(w->ver_offset/2)) * yfac),
- &wop.x, &wop.y );
- wop.x = (wind->ex.x1-(wop.box.x1-wop.box.x0))/2;
- if (wop.x<0) wop.x = 0; /* in case of smaller work area than window */
- wop.behind = -1;
- wimp_open_wind (&wop);
-
- set_window_title (w);
-
- w->next = windows;
- windows = w;
- } /* build_a_window */
-
-
-
- /**********
- Read a dvifile and build a dvi_file structure. Return 0 if no error
- occured, +1 if an error occured and the user has already been notified, -1
- otherwise. */
-
- int
- read_a_file (char *name)
- {
- char *dviread_argv[2], *xname, *real_name;
- struct dvi_file *df;
- struct display *w;
- FILE *f;
-
- if (loading_a_file)
- {
- fatal ("Already loading a file. Please wait.");
- return (1);
- }
-
- /* If NAME is a directory, try looking for a file called dvi in there. If
- this exists, correct NAME. */
-
- xname = malloc (5 + strlen (name));
- sprintf (xname, "%s.dvi", name);
- f = fopen (xname, "rb");
- fclose (f);
- real_name = (f == NULL ? name : xname);
-
- /* If this file is already loaded bring his window to the front so the user
- will see this as well (and spot the `mistake'). */
-
- for (w = windows; w; w = w->next)
- if (strcmp (w->file->f_name, real_name) == 0)
- {
- wimp_wstate r;
-
- wimpt_complain (wimp_get_wind_state (w->w_handle, &r));
- r.o.behind = -1;
- wimpt_complain (wimp_open_wind (&r.o));
- free (xname);
- return (0);
- }
-
- /* Alles klar Herr Commissar. */
-
- df = calloc (1, sizeof (struct dvi_file));
- if (df == NULL)
- {
- fatal ("Out of memory, sorry.\n");
- return (1);
- }
-
- df->f_name = malloc (1 + strlen (real_name));
- if (df->f_name == NULL)
- {
- fatal ("Out of memory, sorry.\n");
- return (1);
- }
-
- strcpy (df->f_name, real_name);
-
- dviread_argv[0] = "6 * 9 == 42";
- dviread_argv[1] = real_name;
- page_ptr = &df->pages;
- current_page_number = 0;
- current_dvi_file = df;
- loading_a_file = TRUE;
- df->complete = FALSE;
-
- /* Switch on hourglass and start reading the dvi file. The accompanying
- visdelay_end () is in DRAW_endpage, where the hourglass is switched off
- after having loaded the first page. */
-
- visdelay_begin ();
- dviread_main (2, dviread_argv);
-
- df->complete = TRUE;
- df->next = dvi_files;
- dvi_files = df;
-
- /* Windows _must_ point to the newly loaded file's window. */
-
- for (w = windows; w; w = w->next)
- if (w->file == df)
- set_window_title (w);
-
- loading_a_file = FALSE;
- free (xname);
- return (0);
- } /* read_a_file */
-
-
-
-
- /* Delete the display_window with window handle H from the list of window
- display's. If no such entry in the list can be found, just return
- without further action. */
-
- void
- delete_display (wimp_w h)
- {
- struct display **w, *t, *t2;
- struct dvi_file *f, **pf;
- int i;
- struct page *p, *q;
-
- for (w = &windows; *w; w = &(*w)->next)
- if ((*w)->w_handle == h)
- break;
-
- if (*w)
- {
- t = *w;
- *w = t->next;
- for (t2 = windows; t2; t2 = t2->next)
- if (t2->file == t->file)
- break;
-
- /* If T2 is NULL, this is the last display onto that dvi file, so the
- dvi file structure can be deleted as well. */
-
- if (t2 == NULL)
- for (pf = &dvi_files; *pf; pf = &(*pf)->next)
- if (*pf == t->file)
- {
- f = *pf;
- *pf = f->next;
- for (i = 0; i < 256; i++)
- if (f->fonts[i])
- free (f->fonts[i]);
- for (p = f->pages; p; p = q)
- {
- #ifdef USE_FLEX
- flex_free ((flex_ptr) &p->texts);
- flex_free ((flex_ptr) &p->rules);
- flex_free ((flex_ptr) &p->chars);
- #else
- free (p->texts);
- free (p->rules);
- free (p->chars);
- #endif
- q = p->next;
- free (p);
- }
- break;
- }
-
- #ifdef USE_FLEX
- flex_free ((flex_ptr) &t->area);
- #else
- free (t->area);
- #endif
- free (t);
- }
- }
-
- /******************************************
-
- DRAW_ routines
-
- ******************************************/
-
-
-
- void
- DRAW_startpage(void)
- {
- struct page *p = xcalloc (1, sizeof (struct page));
-
- p->dvi_page = ++current_page_number;
- p->complete = FALSE;
-
- text_index = 0;
- max_text_index = TEXT_BLOCKSIZE;
-
- #ifdef USE_FLEX
- if (flex_alloc ((flex_ptr) &p->texts, TEXT_BLOCKSIZE * sizeof (struct text)) == 0)
- tfatal ("failed to allocate room for text");
- #else
- p->texts = xmalloc (TEXT_BLOCKSIZE * sizeof (struct text));
- #endif
-
- rule_index = 0;
- max_rule_index = RULE_BLOCKSIZE;
-
- #ifdef USE_FLEX
- if (flex_alloc ((flex_ptr) &p->rules, RULE_BLOCKSIZE * sizeof (struct rule)) == 0)
- tfatal ("failed to allocate room for chars");
- #else
- p->rules = xmalloc (RULE_BLOCKSIZE * sizeof (struct rule));
- #endif
-
- char_index = 0;
- max_char_index = CHAR_BLOCKSIZE;
-
- #ifdef USE_FLEX
- if (flex_alloc ((flex_ptr) &p->chars, CHAR_BLOCKSIZE) == 0)
- tfatal ("failed to allocated room for rules");
- #else
- p->chars = xmalloc (CHAR_BLOCKSIZE);
- #endif
-
- *page_ptr = p;
- page_ptr = &p->next;
- p->things = 0;
- current_page = p;
- }
-
-
-
- void
- DRAW_text(int xl, int yb, int xr, int yt, char *text)
- {
- struct text *t;
- int i, len = 1 + strlen (text);
-
- yt = yt, xr = xr; /* Indeed, to make cc shut up. */
-
- /* If LEN == 1, a `zero string' was passed. This could only come from
- DRAW_char, so we got passed a one-character string with the character 0
- in it. */
-
- if (len == 1)
- len = 2;
-
- if (char_index + len >= max_char_index)
- {
- max_char_index += CHAR_BLOCKSIZE;
- #ifdef USE_FLEX
- if (flex_extend ((flex_ptr) ¤t_page->chars, max_char_index) == 0)
- tfatal ("OUT OF MEMORY");
- #else
- current_page->chars = xrealloc (current_page->chars, max_char_index);
- #endif
- }
-
- for (i = 1; i < len; i++)
- text[i - 1] |= 128;
- strcpy (¤t_page->chars[char_index], text);
-
- if (text_index == max_text_index)
- {
- max_text_index += TEXT_BLOCKSIZE;
- #ifdef USE_FLEX
- if (flex_extend ((flex_ptr) ¤t_page->texts, max_text_index * sizeof (struct text)) == 0)
- tfatal ("OUT OF MEMORY");
- #else
- current_page->texts = xrealloc (current_page->texts, max_text_index * sizeof (struct text));
- #endif
- }
-
- t = ¤t_page->texts[text_index];
- t->font = current_font_handle;
- t->text = char_index;
- t->x = xl;
- t->y = yb;
- t->rx = xr;
- t->ty = yt;
-
- current_page->things++;
- char_index += len;
- text_index++;
-
- if (current_dvi_file->pages->complete && current_page->things % 66 == 0)
- do_a_poll ();
- }
-
-
- /**********
- Write one character. This might be a special character (unprintable ASCII
- code) hence this routine, which tweaks the character and just calls
- DRAW_text to print it. */
-
- void
- DRAW_char(int xl, int yb, char c)
- {
- char a[2];
-
- a[0] = c; a[1] = 0;
- DRAW_text (xl, yb, xl + 100, yb, a);
-
- if (debug)
- fprintf(stderr, "Draw_char(xl = %d, yb = %d, char = %d)\n", xl, yb, c);
- }
-
-
- /**********
- Draw a rule at the specified position (X, Y) and of the specified width DX
- and height DY. */
-
- void
- DRAW_rule(int x, int y, int dy, int dx)
- {
- struct rule *r;
-
- if (rule_index == max_rule_index)
- {
- max_rule_index += RULE_BLOCKSIZE;
- #ifdef USE_FLEX
- if (flex_extend ((flex_ptr) ¤t_page->rules, max_rule_index * sizeof (struct rule)) == 0)
- tfatal ("barf r1");
- #else
- current_page->rules = xrealloc (current_page->rules, max_rule_index * sizeof (struct rule));
- #endif
- }
-
- r = ¤t_page->rules[rule_index];
-
- r->x = x;
- r->y = y;
- r->w = dx;
- r->h = dy;
-
- current_page->things++;
- rule_index++;
-
- #if 0
- printf ("%d %d %d %p %p %p\n", char_index, text_index, rule_index, current_page->chars, current_page->texts, current_page->rules);
- #endif
-
- if (debug)
- fprintf(stderr, "Draw_rule(xl = %d, yb = %d, dx = %d, dy = %d)\n", x, y, dx, dy);
- }
-
-
- /**********
- Select a new current font. */
-
- void
- DRAW_selfont(int fno)
- {
- current_font_handle = fno;
- if (debug) fprintf(stderr, "Draw_selfont (fno = %d)\n", fno);
- }
-
-
- /**********
- Define a font, named FNAME, of size SIZE, and to be identified as FNO.
- SIZE is in 16th of a point. Also check if the font actually exists, so an
- error can be issued, because if the font appears not to be present while
- redrawing the sprite we can't issue an error message. */
-
- void
- DRAW_deffont(int fno, char *fname, int size, int mag)
- {
- char *s;
- struct font_use *f;
- int fh;
-
- s = xmalloc (1 + strlen (fname));
- sprintf (s, "%s", fname);
-
- set_font_path ();
- err = font_find (s, size * mag / 1000, size * mag / 1000, 0, 0, &fh);
- if (err)
- {
- fatal ("Cannot find font `%s': %s\n", fname, err->errmess);
- reset_font_path ();
- do_a_poll ();
- }
- else
- {
- font_lose (fh);
- reset_font_path ();
- }
-
- f = xcalloc (1, sizeof (struct font_use));
- f->name = s;
- f->size = size * mag / 1000;
- current_dvi_file->fonts[fno] = f;
-
- reset_font_path ();
-
- if (debug)
- fprintf(stderr, "Draw_deffont(no = %d, name = \"%s\", size = %d/16)\n", fno, fname, size);
- }
-
-
- /********
- Mark the end of a page. MAXH and MAXV are the observed limits for this
- page; COUNT points to an array of TeX page counters. */
-
- void
- DRAW_endpage(int maxh, int maxv, int *count)
- {
- memcpy (current_page->tex_pages, count, 10 * sizeof (int));
- current_page->complete = TRUE;
- current_dvi_file->height = maxv;
- current_dvi_file->width = maxh;
-
- #ifdef USE_FLEX
- if (flex_extend ((flex_ptr) ¤t_page->texts, text_index * sizeof (struct text)) == 0)
- tfatal ("barf e1");
- if (flex_extend ((flex_ptr) ¤t_page->chars, char_index) == 0)
- tfatal ("barf e2");
- if (flex_extend ((flex_ptr) ¤t_page->rules, rule_index * sizeof (struct rule)) == 0)
- tfatal ("barf e1");
- #else
- current_page->texts = xrealloc (current_page->texts, text_index * sizeof (struct text));
- current_page->chars = xrealloc (current_page->chars, char_index);
- current_page->rules = xrealloc (current_page->rules, rule_index * sizeof (struct rule));
- #endif
-
- current_page->text_max = text_index;
- current_page->rule_max = rule_index;
- current_page->char_max = char_index;
-
- if (debug)
- fprintf(stderr, "Draw_endpage(%d, %d, %d)\n", maxh, maxv, count[0]);
-
- if (current_page_number == 1)
- {
- build_a_window (current_dvi_file, current_dvi_file->pages);
- visdelay_end ();
- }
- }
-
- /* EOF */
-